
#include "ExpressionBuilder.h"

#include "ScriptCompiler/ScriptFileContext.h"
#include "ScriptCompiler/CompilerContext.h"

#include "ScriptCompiler/ASTBuilder/IfBuilder.h"
#include "ScriptCompiler/ASTBuilder/SwitchBuilder.h"
#include "ScriptCompiler/ASTBuilder/FunctionCallBuilder.h"
#include "ScriptCompiler/ASTBuilder/BreakBuilder.h"
#include "ScriptCompiler/ASTBuilder/ContinueBuilder.h"
#include "ScriptCompiler/ASTBuilder/ReturnBuilder.h"
#include "ScriptCompiler/ASTBuilder/WhileBuilder.h"
#include "ScriptCompiler/ASTBuilder/DoWhileBuilder.h"
#include "ScriptCompiler/ASTBuilder/ForBuilder.h"
#include "ScriptCompiler/ASTBuilder/DecoratorBuilder.h"
#include "ScriptCompiler/ASTBuilder/TypeBuilder.h"
#include "ScriptCompiler/ASTBuilder/SentenceIndexerBuilder.h"

#include "ScriptCompiler/AST/ExpressionNode.h"
#include "ScriptCompiler/AST/IfNode.h"
#include "ScriptCompiler/AST/SwitchNode.h"
#include "ScriptCompiler/AST/FunctionCallNode.h"
#include "ScriptCompiler/AST/LiteralNode.h"
#include "ScriptCompiler/AST/MonocularOperatorNode.h"
#include "ScriptCompiler/AST/BinocularOperatorNode.h"
#include "ScriptCompiler/AST/VariableDeclarationNode.h"
#include "ScriptCompiler/AST/ParenthesesNode.h"
#include "ScriptCompiler/AST/BracketNode.h"
#include "ScriptCompiler/AST/TypeCastNode.h"
#include "ScriptCompiler/AST/IdentifierNode.h"
#include "ScriptCompiler/AST/TypeNode.h"
#include "ScriptCompiler/AST/VariableDeclarationNode.h"
#include "ScriptCompiler/AST/EmptyNode.h"
#include "ScriptCompiler/AST/BreakNode.h"
#include "ScriptCompiler/AST/ContinueNode.h"
#include "ScriptCompiler/AST/ReturnNode.h"
#include "ScriptCompiler/AST/WhileNode.h"
#include "ScriptCompiler/AST/DoWhileNode.h"
#include "ScriptCompiler/AST/ForNode.h"
#include "ScriptCompiler/AST/ValueNode.h"
#include "ScriptCompiler/AST/DecoratorNode.h"
#include "ScriptCompiler/AST/MemberAccessNode.h"
#include "ScriptCompiler/AST/AssignNode.h"
#include "ScriptCompiler/AST/NewNode.h"
#include "ScriptCompiler/AST/SentenceIndexerNode.h"
#include "ScriptCompiler/AST/SentenceBlockNode.h"
#include "ScriptCompiler/AST/PositiveNode.h"
#include "ScriptCompiler/AST/NegativeNode.h"

#include "ScriptCompiler/AST/QuestionColonOperatorNode.h"

#include "ScriptCompiler/ASTBuilder/NewBuilder.h"

CExpressionBuilder::CExpressionBuilder(
    std::shared_ptr<CScriptFileContext> InContext
    , uint64_t InEndTokenIndex )
{
    Context = InContext;
    EndTokenIndex=InEndTokenIndex;
}

bool CExpressionBuilder::ReadCurentToken()
{

    auto Token = Context->GetCurrentToken();


    //build keyword head statements
    switch(Token->Type)
    {
        case EScriptTokenType::Continue:
        case EScriptTokenType::Break:
        case EScriptTokenType::Return:
        case EScriptTokenType::For:
        case EScriptTokenType::Do:
        case EScriptTokenType::While:
        case EScriptTokenType::Switch:
        case EScriptTokenType::If:
        {
            Context->RaiseError(10092,Token,U"Unexpected token here, do you forget ';' before here ?");
            return false;
        }
        case EScriptTokenType::New:
        {
            auto NewBuilder = std::make_shared<CNewBuilder>(Context);
            if(!NewBuilder->ReadCurentToken())
            {
                return false;
            }

            Result= NewBuilder->Result;

            //check is fully parsed
            if(Context->CurrentTokenIndex<EndTokenIndex)
            {
                auto Token = Context->GetCurrentToken();
                Context->RaiseError(10093,Token,U"Unexpected token after new expression");
                return false;
            }
            
            //Result->File=Context;
            return true;
        }

    };
    
    //check if this is a assignment
    {
        //try to find '='
        auto AssigmentOperator = FindNextAssigmentOperator(Context,EndTokenIndex);
        if(AssigmentOperator.HasValue())
        {
            //this is a assignment
            auto AssignmentNode = std::make_shared<CAssignNode >(Context);
            Result=AssignmentNode;
            AssignmentNode->Operator = Context->GetToken(AssigmentOperator.GetValue());

            //read left operand
            {
                auto ExpressionBuilder = std::make_shared<CExpressionBuilder>(Context,AssigmentOperator.GetValue());
                if(!ExpressionBuilder->ReadCurentToken())
                {
                    return false;
                }

                AssignmentNode->LeftOperand=ExpressionBuilder->Result;
            }

            Context->CurrentTokenIndex++; //skip '='

            //read right operand
            {
                auto ExpressionBuilder = std::make_shared<CExpressionBuilder>(Context,EndTokenIndex);
                if(!ExpressionBuilder->ReadCurentToken())
                {
                    return false;
                }

                AssignmentNode->RightOperand=ExpressionBuilder->Result;
            }
            //Result->File=Context;
            return true;


        }
    }

    Result=IteralTokens(-1);
    if(!Result)
    {
        return false;
    }
    return true;

    // //a list of tokens and sentences
    // std::list< RawASTNode>  RawNodeList;

    // //read all tokens until semicolon
    // while (Context->CurrentTokenIndex<EndTokenIndex)
    // {
    //     Token = Context->GetCurrentToken();

    //     if(Token->Type == EScriptTokenType::LeftParentheses)
    //     {
    //         auto ParenthesesNode = std::make_shared<CParenthesesNode>(Context);
    //         ParenthesesNode->LeftParentheses = Token;
    //         Context->CurrentTokenIndex++; //skip left parenthesis

    //         //find ')'
    //         auto RightParenthesesPos=FindPairedParentheses(Context);
    //         if(!RightParenthesesPos)
    //         {
    //             //raise error, require ')'
    //             Context->RaiseError(10103,Context->GetCurrentToken(),U"Expected paired ')' ");
    //             return false;
    //         }

    //         auto ExpressionBuilder = std::make_shared<CExpressionBuilder>(Context,RightParenthesesPos.GetValue());
    //         if(!ExpressionBuilder->ReadCurentToken())
    //         {
    //             return false;
    //         }

    //         ParenthesesNode->Expression = ExpressionBuilder->Result;
    //         RawNodeList.push_back(std::static_pointer_cast<CExpressionNode>(ParenthesesNode));

    //         //skip right parenthesis
    //         {
    //             auto RightParentheses = Context->GetCurrentToken();
    //             if(RightParentheses->Type != EScriptTokenType::RightParentheses)
    //             {
    //                 Context->RaiseError(10103,RightParentheses,U"Expecting ')'");
    //                 return false;
    //             }
    //             Context->CurrentTokenIndex++; //skip right parenthesis
    //         }

    //         continue;
    //     }

    //     if(Token->Type == EScriptTokenType::LeftBracket)
    //     {
    //         auto SentenceIndexerBuilder= std::make_shared<CSentenceIndexerBuilder>(Context);
    //         if(!SentenceIndexerBuilder->ReadCurentToken())
    //         {
    //             return false;
    //         }
            
    //         //check if former node is a member access node/ identifier node
    //         if(!RawNodeList.empty())
    //         {
    //             auto FormerNode = RawNodeList.back();
    //             if(FormerNode.IsA<std::shared_ptr<CExpressionNode>>())
    //             {
    //                 //get sentence node
    //                 auto SentenceNode = std::static_pointer_cast<CExpressionNode>(FormerNode.Get<std::shared_ptr<CExpressionNode>>());

    //                 if(SentenceNode->Type== EASTNodeType::MemberAccess)
    //                 {
    //                     //this is a member access node
    //                     auto MemberAccessNode = std::static_pointer_cast<CMemberAccessNode>(SentenceNode);
                        
    //                     //append indexer
    //                     MemberAccessNode->AccessOperators.Add(SentenceIndexerBuilder->Result->GetFirstToken());
    //                     MemberAccessNode->AccessChain.Add(SentenceIndexerBuilder->Result);

    //                     continue;
    //                 }
    //                 else if(SentenceNode->Type== EASTNodeType::Identifier)
    //                 {
    //                     //this is a member access node
    //                     auto IdentifierNode = std::static_pointer_cast<CIdentifierNode>(SentenceNode);
    //                     RawNodeList.pop_back();
                        
    //                     //append indexer
    //                     auto MemberAccessNode = std::make_shared<CMemberAccessNode>(Context);
    //                     MemberAccessNode->AccessChain.Add(SentenceNode); //identifier node
    //                     MemberAccessNode->AccessOperators.Add(SentenceIndexerBuilder->Result->GetFirstToken());
    //                     MemberAccessNode->AccessChain.Add(SentenceIndexerBuilder->Result); //indexer node
    //                     RawNodeList.push_back(std::static_pointer_cast<CExpressionNode>(MemberAccessNode));
    //                     continue;

    //                 }

    //             }
    //         }

    //         //raise error, indexer cant be first 
    //         Context->RaiseError(10104,SentenceIndexerBuilder->Result->GetFirstToken(),U"Indexer can only be used after member access or identifier");
    //         return false;
    //     }


    //     if(Token->Type == EScriptTokenType::LiteralChar
    //         || Token->Type == EScriptTokenType::LiteralString
    //         || Token->Type == EScriptTokenType::LiteralNumber
    //         || Token->Type == EScriptTokenType::LiteralBool
    //         || Token->Type == EScriptTokenType::Null
    //     )
    //     {
    //         auto LiterialNode = std::make_shared<CLiteralNode>(Context);
    //         LiterialNode->Value = Token;
    //         RawNodeList.push_back(std::static_pointer_cast<CExpressionNode>(LiterialNode));
    //         Context->CurrentTokenIndex++;
    //         continue;
    //     }

    //     if(Token->Type == EScriptTokenType::Value)
    //     {
    //         auto ValueNode = std::make_shared<CValueNode>(Context);
    //         ValueNode->Value = Token;
    //         RawNodeList.push_back(std::static_pointer_cast<CExpressionNode>(ValueNode));
    //         Context->CurrentTokenIndex++;
    //         continue;
    //     }

    //     //read function call node
    //     if(Token->Type == EScriptTokenType::Identifier)
    //     {
    //         auto NextToken = Context->GetNextToken();

    //         if(NextToken->Type == EScriptTokenType::LeftParentheses)
    //         {
    //             //this is a function call
    //             auto FunctionCallBuilder = std::make_shared<CFunctionCallBuilder>(Context);
    //             if(!FunctionCallBuilder->ReadCurentToken())
    //             {
    //                 return false;
    //             }

    //             RawNodeList.push_back(std::static_pointer_cast<CExpressionNode> (FunctionCallBuilder->Result));
    //             continue;
    //         }


    //         auto IdentifierNode = std::make_shared<CIdentifierNode>(Context);
    //         IdentifierNode->Identifier = Token;
    //         RawNodeList.push_back(std::static_pointer_cast<CExpressionNode> (IdentifierNode));
    //         Context->CurrentTokenIndex++;
    //         continue;
    //     }

    //     //normal token
    //     RawNodeList.push_back(Token);
    //     Context->CurrentTokenIndex++;

    // }

    // if(RawNodeList.empty())
    // {
    //     Result=std::make_shared<CEmptyNode>(Context);
    //     return true;
    // }

    // //seperate tokens into sentences by operators ,fron low priority to high priority
    // Result=BuildExpression(RawNodeList);

    // //Result->File=Context;
    // return true;


}

// std::shared_ptr<CExpressionNode> CExpressionBuilder::BuildExpression(const std::list<RawASTNode> &RawNodeList)
// {
//     if(RawNodeList.empty())
//     {
//         return std::shared_ptr<CEmptyNode>();
//     }

//     if(RawNodeList.size() == 1)
//     {
//         if(RawNodeList.front().IsA<std::shared_ptr<CExpressionNode>>())
//         {
//             return RawNodeList.front().Get<std::shared_ptr<CExpressionNode>>();
//         }
//         else
//         {
//             auto Token = RawNodeList.front().Get<std::shared_ptr<CScriptToken>>();
//             Context->RaiseError(10105,Token,U"unparsed single token");
//             return nullptr;
//         }
//     }




//     // //1. seperate by comma
//     // {
//     //     auto Found=std::find_if(RawNodeList.begin(),RawNodeList.end(),[](const RawASTNode& InRawNode){
//     //         return InRawNode.IsA<std::shared_ptr<CScriptToken>>() && InRawNode.Get<std::shared_ptr<CScriptToken>>()->Type == EScriptTokenType::Comma;
//     //     });
    
//     //     if(Found != RawNodeList.end())
//     //     {

//     //         auto CommaNode = std::make_shared<CBinocularOperatorNode>(Context);
//     //         CommaNode->Operator = Found->Get<std::shared_ptr<CScriptToken>>();

//     //         CommaNode->LeftOperand=BuildExpression( std::list<RawASTNode>(RawNodeList.begin(),Found));
//     //         Found++;
//     //         CommaNode->RightOperand=BuildExpression( std::list<RawASTNode>(Found,RawNodeList.end()));
//     //         return CommaNode;
//     //     }
//     // }

//     //1 .seperate by assign and =>
//     {
//         auto Found=std::find_if(RawNodeList.begin(),RawNodeList.end(),[](const RawASTNode& InRawNode){
//             if(!InRawNode.IsA<std::shared_ptr<CScriptToken>>() )
//             {
//                 return false;
//             }

//             auto TokenType=InRawNode.Get<std::shared_ptr<CScriptToken>>()->Type;

//             return Token::IsAssignOperator(TokenType)
//                 || TokenType == EScriptTokenType::LambdaOperator
//                 ;
//         });
    
//         if(Found != RawNodeList.end())
//         {
//             auto Token=Found->Get<std::shared_ptr<CScriptToken>>();
//             if(Token->Type == EScriptTokenType::LambdaOperator)
//             {
//                 auto Lambda = std::make_shared<CBinocularOperatorNode>(Context);
//                 Lambda->Operator = Found->Get<std::shared_ptr<CScriptToken>>();

//                 Lambda->LeftOperand=BuildExpression( std::list<RawASTNode>(RawNodeList.begin(),Found));
//                 Found++;
//                 Lambda->RightOperand=BuildExpression( std::list<RawASTNode>(Found,RawNodeList.end()));
//                 return Lambda;
//             }
//             else
//             {

//                 auto AssignmentNode = std::make_shared<CAssignNode >(Context);
//                 AssignmentNode->Operator = Found->Get<std::shared_ptr<CScriptToken>>();

//                 AssignmentNode->LeftOperand=BuildExpression( std::list<RawASTNode>(RawNodeList.begin(),Found));
//                 Found++;
//                 AssignmentNode->RightOperand=BuildExpression( std::list<RawASTNode>(Found,RawNodeList.end()));
//                 return AssignmentNode;
//             }
//         }
//     }

//     //3. seperate by ?:
//     {
//         auto QuestionFound=std::find_if(RawNodeList.begin(),RawNodeList.end(),[](const RawASTNode& InRawNode){
//             return InRawNode.IsA<std::shared_ptr<CScriptToken>>() && InRawNode.Get<std::shared_ptr<CScriptToken>>()->Type == EScriptTokenType::Question;
//         });

//         if(QuestionFound == RawNodeList.begin())
//         {
//             // do not have condition
//             Context->RaiseError(10106, QuestionFound->Get<std::shared_ptr<CScriptToken>>(),U" ?: statement must have condition before '?' ");
//             return nullptr;
//         }


//         if(QuestionFound != RawNodeList.end())
//         {
//             //find :
//             auto ColonFound=std::find_if(QuestionFound,RawNodeList.end(),[](const RawASTNode& InRawNode){
//                 return InRawNode.IsA<std::shared_ptr<CScriptToken>>() && InRawNode.Get<std::shared_ptr<CScriptToken>>()->Type == EScriptTokenType::Colon;
//             });


//             if(ColonFound != RawNodeList.end())
//             {
//                 auto QuestionColonNode = std::make_shared<CQuestionColonOperatorNode>(Context);
//                 QuestionColonNode ->Condition=BuildExpression( std::list<RawASTNode>(std::prev(QuestionFound),QuestionFound));

//                 std::shared_ptr<CExpressionNode> TrueBranch=BuildExpression( std::list<RawASTNode>(std::next(QuestionFound),ColonFound));
//                 QuestionColonNode->TrueBranch=TrueBranch;
//                 ColonFound++;

//                 std::shared_ptr<CExpressionNode> FalseBranch= BuildExpression( std::list<RawASTNode>(std::next(ColonFound), std::next(ColonFound,2)));
//                 QuestionColonNode->FalseBranch=FalseBranch;

//                 //replace ? and : with if node
//                 std::list<RawASTNode> NewRawNodeList;
//                 NewRawNodeList.insert(NewRawNodeList.end(),RawNodeList.begin(),std::prev(QuestionFound));
//                 NewRawNodeList.push_back(std::static_pointer_cast<CExpressionNode>(QuestionColonNode));
//                 NewRawNodeList.insert(NewRawNodeList.end(),std::next(ColonFound,2),RawNodeList.end());
                
//                 return BuildExpression(NewRawNodeList);
//             }
//             else
//             {
//                 Context->RaiseError(10107, QuestionFound->Get<std::shared_ptr<CScriptToken>>(),U" ?: statement must have ':' ");
//                 return nullptr;
//             }

//         }
    
//     }


//     //4. seperate by ||
//     {
//         auto Found=std::find_if(RawNodeList.begin(),RawNodeList.end(),[](const RawASTNode& InRawNode){
//             return InRawNode.IsA<std::shared_ptr<CScriptToken>>() && InRawNode.Get<std::shared_ptr<CScriptToken>>()->Type == EScriptTokenType::OrOr;
//         });
    
//         if(Found != RawNodeList.end())
//         {

//             auto BinocularOperatorNode = std::make_shared<CBinocularOperatorNode>(Context);
//             BinocularOperatorNode->Operator = Found->Get<std::shared_ptr<CScriptToken>>();

//             BinocularOperatorNode->LeftOperand=BuildExpression( std::list<RawASTNode>(RawNodeList.begin(),Found));
//             BinocularOperatorNode->RightOperand=BuildExpression( std::list<RawASTNode>(std::next(Found),RawNodeList.end()));
//             return BinocularOperatorNode;
//         }
//     }

//     //5 .seperate by &&
//     {
//         auto Found=std::find_if(RawNodeList.begin(),RawNodeList.end(),[](const RawASTNode& InRawNode){
//             return InRawNode.IsA<std::shared_ptr<CScriptToken>>() && InRawNode.Get<std::shared_ptr<CScriptToken>>()->Type == EScriptTokenType::AndAnd;
//         });
    
//         if(Found != RawNodeList.end())
//         {

//             auto BinocularOperatorNode = std::make_shared<CBinocularOperatorNode>(Context);
//             BinocularOperatorNode->Operator = Found->Get<std::shared_ptr<CScriptToken>>();

//             BinocularOperatorNode->LeftOperand=BuildExpression( std::list<RawASTNode>(RawNodeList.begin(),Found));
//             BinocularOperatorNode->RightOperand=BuildExpression( std::list<RawASTNode>(std::next(Found),RawNodeList.end()));
//             return BinocularOperatorNode;
//         }
//     }

//     //6 .seperate by |
//     {
//         auto Found=std::find_if(RawNodeList.begin(),RawNodeList.end(),[](const RawASTNode& InRawNode){
//             return InRawNode.IsA<std::shared_ptr<CScriptToken>>() && InRawNode.Get<std::shared_ptr<CScriptToken>>()->Type == EScriptTokenType::Or;
//         });
    
//         if(Found != RawNodeList.end())
//         {

//             auto BinocularOperatorNode = std::make_shared<CBinocularOperatorNode>(Context);
//             BinocularOperatorNode->Operator = Found->Get<std::shared_ptr<CScriptToken>>();

//             BinocularOperatorNode->LeftOperand=BuildExpression( std::list<RawASTNode>(RawNodeList.begin(),Found));
//             BinocularOperatorNode->RightOperand=BuildExpression( std::list<RawASTNode>(std::next(Found),RawNodeList.end()));
//             return BinocularOperatorNode;
//         }
//     }


//     //7 .seperate by ^
//     {
//         auto Found=std::find_if(RawNodeList.begin(),RawNodeList.end(),[](const RawASTNode& InRawNode){
//             return InRawNode.IsA<std::shared_ptr<CScriptToken>>() && InRawNode.Get<std::shared_ptr<CScriptToken>>()->Type == EScriptTokenType::Xor;
//         });
    
//         if(Found != RawNodeList.end())
//         {

//             auto BinocularOperatorNode = std::make_shared<CBinocularOperatorNode>(Context);
//             BinocularOperatorNode->Operator = Found->Get<std::shared_ptr<CScriptToken>>();

//             BinocularOperatorNode->LeftOperand=BuildExpression( std::list<RawASTNode>(RawNodeList.begin(),Found));
//             BinocularOperatorNode->RightOperand=BuildExpression( std::list<RawASTNode>(std::next(Found),RawNodeList.end()));
//             return BinocularOperatorNode;
//         }
//     }


//     //8 .seperate by &
//     {
//         auto Found=std::find_if(RawNodeList.begin(),RawNodeList.end(),[](const RawASTNode& InRawNode){
//             return InRawNode.IsA<std::shared_ptr<CScriptToken>>() && InRawNode.Get<std::shared_ptr<CScriptToken>>()->Type == EScriptTokenType::And;
//         });
    
//         if(Found != RawNodeList.end())
//         {

//             auto BinocularOperatorNode = std::make_shared<CBinocularOperatorNode>(Context);
//             BinocularOperatorNode->Operator = Found->Get<std::shared_ptr<CScriptToken>>();

//             BinocularOperatorNode->LeftOperand=BuildExpression( std::list<RawASTNode>(RawNodeList.begin(),Found));
//             BinocularOperatorNode->RightOperand=BuildExpression( std::list<RawASTNode>(std::next(Found),RawNodeList.end()));
//             return BinocularOperatorNode;
//         }
//     }

//     //9 .seperate by == and !=
//     {
//         auto Found=std::find_if(RawNodeList.begin(),RawNodeList.end(),[](const RawASTNode& InRawNode){
//             return InRawNode.IsA<std::shared_ptr<CScriptToken>>() && (InRawNode.Get<std::shared_ptr<CScriptToken>>()->Type == EScriptTokenType::Equal || InRawNode.Get<std::shared_ptr<CScriptToken>>()->Type == EScriptTokenType::NotEqual);
//         });
    
//         if(Found != RawNodeList.end())
//         {

//             auto BinocularOperatorNode = std::make_shared<CBinocularOperatorNode>(Context);
//             BinocularOperatorNode->Operator = Found->Get<std::shared_ptr<CScriptToken>>();

//             BinocularOperatorNode->LeftOperand=BuildExpression( std::list<RawASTNode>(RawNodeList.begin(),Found));
//             BinocularOperatorNode->RightOperand=BuildExpression( std::list<RawASTNode>(std::next(Found),RawNodeList.end()));
//             return BinocularOperatorNode;
//         }
//     }

//     //10. seperate by > < <= >=
//     {
//         auto Found=std::find_if(RawNodeList.begin(),RawNodeList.end(),[](const RawASTNode& InRawNode){
//             if(!InRawNode.IsA<std::shared_ptr<CScriptToken>>() )
//             {
//                 return false;
//             }

//             auto TokenType=InRawNode.Get<std::shared_ptr<CScriptToken>>()->Type;
//             return TokenType == EScriptTokenType::Less 
//             || TokenType == EScriptTokenType::LessEqual 
//             || TokenType == EScriptTokenType::Greater 
//             || TokenType == EScriptTokenType::GreaterEqual;

//         });

//         if(Found != RawNodeList.end())
//         {

//             auto BinocularOperatorNode = std::make_shared<CBinocularOperatorNode>(Context);
//             BinocularOperatorNode->Operator = Found->Get<std::shared_ptr<CScriptToken>>();

//             BinocularOperatorNode->LeftOperand=BuildExpression( std::list<RawASTNode>(RawNodeList.begin(),Found));
//             BinocularOperatorNode->RightOperand=BuildExpression( std::list<RawASTNode>(std::next(Found),RawNodeList.end()));
//             return BinocularOperatorNode;
//         }

//     }

//     //11 .seperate by << >>
//     {
//         auto Found=std::find_if(RawNodeList.begin(),RawNodeList.end(),[](const RawASTNode& InRawNode){
//             if(!InRawNode.IsA<std::shared_ptr<CScriptToken>>() )
//             {
//                 return false;
//             }

//             auto TokenType=InRawNode.Get<std::shared_ptr<CScriptToken>>()->Type;
//             return TokenType == EScriptTokenType::LeftShift 
//             || TokenType == EScriptTokenType::RightShift;

//         });

//         if(Found != RawNodeList.end())
//         {

//             auto BinocularOperatorNode = std::make_shared<CBinocularOperatorNode>(Context);
//             BinocularOperatorNode->Operator = Found->Get<std::shared_ptr<CScriptToken>>();

//             BinocularOperatorNode->LeftOperand=BuildExpression( std::list<RawASTNode>(RawNodeList.begin(),Found));
//             BinocularOperatorNode->RightOperand=BuildExpression( std::list<RawASTNode>(std::next(Found),RawNodeList.end()));
//             return BinocularOperatorNode;
//         }

//     }

//     //12 seperate by + -
//     {
//         auto Found=std::find_if(RawNodeList.begin(),RawNodeList.end(),[](const RawASTNode& InRawNode){
//             if(!InRawNode.IsA<std::shared_ptr<CScriptToken>>() )
//             {
//                 return false;
//             }

//             auto TokenType=InRawNode.Get<std::shared_ptr<CScriptToken>>()->Type;
//             return TokenType == EScriptTokenType::Plus 
//             || TokenType == EScriptTokenType::Minus;

//         });

//         if(Found != RawNodeList.end())
//         {
//             std::shared_ptr<CScriptToken> Operator = Found->Get<std::shared_ptr<CScriptToken>>();
//             std::shared_ptr<CExpressionNode> LeftOperand=BuildExpression( std::list<RawASTNode>(RawNodeList.begin(),Found));
//             std::shared_ptr<CExpressionNode> RightOperand=BuildExpression( std::list<RawASTNode>(std::next(Found),RawNodeList.end()));

//             //raise error if right operand is empty
//             if(!RightOperand)
//             {
//                 Context->RaiseError(10171,Operator,U"Expecting right operand");
//                 return nullptr;
//             }

//             if(!LeftOperand)
//             {
//                 if(Operator->Type == EScriptTokenType::Plus)
//                 {
//                     //this is a positive expression
//                     auto PositiveExpression=std::make_shared<CPositiveNode>(Context);
//                     PositiveExpression->Plus=Operator;
//                     PositiveExpression->Value=RightOperand;
//                     return PositiveExpression;
//                 }
//                 else
//                 {
//                     //this is a negative 
//                     auto NegativeExpression=std::make_shared<CNegativeNode>(Context);
//                     NegativeExpression->Minus=Operator;
//                     NegativeExpression->Value=RightOperand;
//                     return NegativeExpression;
//                 }
//             }

//             auto BinocularOperatorNode = std::make_shared<CBinocularOperatorNode>(Context);
//             BinocularOperatorNode->Operator = Found->Get<std::shared_ptr<CScriptToken>>();

//             BinocularOperatorNode->LeftOperand=BuildExpression( std::list<RawASTNode>(RawNodeList.begin(),Found));
//             BinocularOperatorNode->RightOperand=BuildExpression( std::list<RawASTNode>(std::next(Found),RawNodeList.end()));
//             return BinocularOperatorNode;
//         }

//     }

//     //13 seperate by * / %
//     {
//         auto Found=std::find_if(RawNodeList.begin(),RawNodeList.end(),[](const RawASTNode& InRawNode){
//             if(!InRawNode.IsA<std::shared_ptr<CScriptToken>>() )
//             {
//                 return false;
//             }

//             auto TokenType=InRawNode.Get<std::shared_ptr<CScriptToken>>()->Type;
//             return TokenType == EScriptTokenType::Multiply 
//             || TokenType == EScriptTokenType::Divide 
//             || TokenType == EScriptTokenType::Mod;

//         });

//         if(Found != RawNodeList.end())
//         {

//             auto BinocularOperatorNode = std::make_shared<CBinocularOperatorNode>(Context);
//             BinocularOperatorNode->Operator = Found->Get<std::shared_ptr<CScriptToken>>();

//             BinocularOperatorNode->LeftOperand=BuildExpression( std::list<RawASTNode>(RawNodeList.begin(),Found));
//             BinocularOperatorNode->RightOperand=BuildExpression( std::list<RawASTNode>(std::next(Found),RawNodeList.end()));
//             return BinocularOperatorNode;
//         }

//     }

//     //14 seperate by ++ -- ! ~ - + (type)  from right to left , ++ -- is at left of variable
//     {
//         auto Found=std::find_if(std::next (RawNodeList.rbegin()),RawNodeList.rend(),[&RawNodeList](const RawASTNode& InRawNode){
            
//             //check new InRawNode is first node in list
//             if(*RawNodeList.rbegin() == InRawNode)
//             {
//                 return false;
//             }

//             if(!InRawNode.IsA<std::shared_ptr<CScriptToken>>() )
//             {

//                 auto Node=InRawNode.Get<std::shared_ptr<CExpressionNode>>();
//                 if(Node->Type == EASTNodeType::Parentheses)
//                 {
//                     return true;
//                 }

//                 return false;
//             }

//             auto TokenType=InRawNode.Get<std::shared_ptr<CScriptToken>>()->Type;
//             return TokenType == EScriptTokenType::PlusPlus 
//             || TokenType == EScriptTokenType::MinusMinus 
//             || TokenType == EScriptTokenType::NotOperator 
//             || TokenType == EScriptTokenType::Tilde 
//             || TokenType == EScriptTokenType::Plus 
//             || TokenType == EScriptTokenType::Minus ;

//         });

//         if(Found != RawNodeList.rend())
//         {
//             if(Found->IsA<std::shared_ptr<CScriptToken>>())
//             {
//                 auto Token=Found->Get<std::shared_ptr<CScriptToken>>();

//                 auto MonoOperatorNode = std::make_shared<CMonocularOperatorNode>(Context);
//                 MonoOperatorNode->Operator = Token;
//                 MonoOperatorNode->Operand=BuildExpression( std::list<RawASTNode>(Found.base(),RawNodeList.end()));


//                 //repalce the tokens from Found to end with the node
//                 auto NewList=std::list<RawASTNode>(RawNodeList.begin(),std::prev(Found.base()));
//                 NewList.push_back(std::static_pointer_cast<CExpressionNode>(MonoOperatorNode));
//                 return BuildExpression(NewList);

//             }
//             else
//             {
//                 //it is a type cast
//                 auto ParenthesesNode= std::static_pointer_cast<CParenthesesNode>(Found->Get<std::shared_ptr<CExpressionNode>>());

//                 auto TypeCastNode = std::make_shared<CTypeCastNode>(Context);
//                 TypeCastNode->LeftParentheses=ParenthesesNode->LeftParentheses;
//                 TypeCastNode->Type=ParenthesesNode->Expression;
//                 TypeCastNode->Expression=BuildExpression( std::list<RawASTNode>(Found.base(),RawNodeList.end()));

//                 //repalce the tokens from Found to end with the node
//                 auto NewList=std::list<RawASTNode>(RawNodeList.begin(),std::prev(Found.base()));
//                 NewList.push_back(std::static_pointer_cast<CExpressionNode>(TypeCastNode));
//                 return BuildExpression(NewList);
//             }
//         }

//     }


//     //15 seperate by . -> ++ -- form left to right  , ++ -- is at right of variable
//     {
//         auto Found=std::find_if(RawNodeList.begin(),RawNodeList.end(),[](const RawASTNode& InRawNode){
//             if(!InRawNode.IsA<std::shared_ptr<CScriptToken>>() )
//             {
//                 return false;
//             }

//             auto TokenType=InRawNode.Get<std::shared_ptr<CScriptToken>>()->Type;
//             return TokenType == EScriptTokenType::Dot 
//             || TokenType == EScriptTokenType::Arrow
//             || TokenType == EScriptTokenType::PlusPlus
//             || TokenType == EScriptTokenType::MinusMinus;

//         });

//         if(Found != RawNodeList.end())
//         {
//             auto Token=Found->Get<std::shared_ptr<CScriptToken>>();

//             switch(Token->Type)
//             {
//                 case EScriptTokenType::Dot:
//                 case EScriptTokenType::Arrow:
//                 {
//                     if(Found == RawNodeList.begin())
//                     {
//                         Context->RaiseError(10108,Token, U" '.'/'->'  must have a former node to access");
//                         return nullptr;
//                     }

//                     //former node
//                     auto FormerNode= * std::prev(Found);
//                     if(FormerNode.IsA<std::shared_ptr<CScriptToken>>())
//                     {
//                         auto FormerToken=FormerNode.Get<std::shared_ptr<CScriptToken>>();
//                         Context->RaiseError(10109,FormerToken, U"is not accessable");
//                         return nullptr;
//                     }

//                     auto FormerSentenceNode=FormerNode.Get<std::shared_ptr<CExpressionNode>>();

//                     if(FormerSentenceNode->Type != EASTNodeType::Identifier
//                         && FormerSentenceNode->Type != EASTNodeType::MemberAccess //append to member access
//                         && FormerSentenceNode->Type != EASTNodeType::FunctionCall
//                         && FormerSentenceNode->Type != EASTNodeType::Literal  //such as 1.ToString()
//                     )
//                     {
//                         Context->RaiseError(10110,Token, U" former node is not accessable");
//                         return nullptr;
//                     }

//                     if(Found == std::prev(RawNodeList.end()))
//                     {
//                         Context->RaiseError(10111,Token, U" '.'/'->'  must have a latter node to access");
//                         return nullptr;
//                     }

//                     auto LatterNode= * std::next(Found);

//                     if(LatterNode.IsA<std::shared_ptr<CScriptToken>>())
//                     {
//                         auto LatterToken=LatterNode.Get<std::shared_ptr<CScriptToken>>();
//                         Context->RaiseError(10112,LatterToken, U"is not accessable");
//                         return nullptr;
//                     }

//                     auto LatterSentenceNode=LatterNode.Get<std::shared_ptr<CExpressionNode>>();

//                     if(LatterSentenceNode->Type != EASTNodeType::Identifier 
//                         && LatterSentenceNode->Type != EASTNodeType::MemberAccess
//                         && LatterSentenceNode->Type != EASTNodeType::FunctionCall )
//                     {
//                         Context->RaiseError(10113,Token, U" latter node is not accessable");
//                         return nullptr;
//                     }

//                     std::shared_ptr<CMemberAccessNode> MemberAccessNode;

//                     if(FormerSentenceNode->Type == EASTNodeType::MemberAccess)
//                     {
//                         MemberAccessNode=std::static_pointer_cast<CMemberAccessNode>(FormerSentenceNode);
//                     }
//                     else
//                     {
//                         MemberAccessNode = std::make_shared<CMemberAccessNode>(Context);
//                         MemberAccessNode->AccessChain.Add(FormerSentenceNode);
//                     }

//                     MemberAccessNode->AccessOperators.Add(Token);

//                     if(LatterSentenceNode->Type == EASTNodeType::MemberAccess)
//                     {
//                         auto LatterMemberAccessNode=std::static_pointer_cast<CMemberAccessNode>(LatterSentenceNode);
//                         MemberAccessNode->AccessChain.Append(LatterMemberAccessNode->AccessChain);
//                         MemberAccessNode->AccessOperators.Add(LatterMemberAccessNode->AccessChain[0]->GetFirstToken());
//                         MemberAccessNode->AccessOperators.Append(LatterMemberAccessNode->AccessOperators);
//                     }
//                     else
//                     {
//                         MemberAccessNode->AccessChain.Add(LatterSentenceNode);
//                     }

//                     //detect next access
//                     auto It=std::next(Found,2);
//                     while(It!= RawNodeList.end())
//                     {
//                         //check if it is a access operator
//                         if(!It->IsA<std::shared_ptr<CScriptToken>>())
//                         {
//                             break;
//                         }

//                         auto NextToken=It->Get<std::shared_ptr<CScriptToken>>();
//                         if(NextToken->Type != EScriptTokenType::Dot && NextToken->Type != EScriptTokenType::Arrow)
//                         {
//                             break;
//                         }

//                         //check if it is a accessable node
//                         auto NextNode= * std::next(It);
//                         if(!NextNode.IsA<std::shared_ptr<CExpressionNode>>())
//                         {
//                             auto NextToken=NextNode.Get<std::shared_ptr<CScriptToken>>();
//                             Context->RaiseError(10114,NextToken, U" latter node is not accessable");
//                             return nullptr;
//                         }

//                         auto NextSentenceNode=NextNode.Get<std::shared_ptr<CExpressionNode>>();
//                         if(NextSentenceNode->Type != EASTNodeType::Identifier 
//                             && NextSentenceNode->Type != EASTNodeType::MemberAccess
//                             && NextSentenceNode->Type != EASTNodeType::FunctionCall )
//                         {
//                             Context->RaiseError(10115,NextToken, U" latter node is not accessable");
//                             return nullptr;
//                         }

//                         //append to member access
//                         if(NextSentenceNode->Type==EASTNodeType::MemberAccess)
//                         {
//                             auto LatterMemberAccessNode=std::static_pointer_cast<CMemberAccessNode>(NextSentenceNode);
//                             MemberAccessNode->AccessOperators.Add(LatterMemberAccessNode->AccessChain[0]->GetFirstToken());
//                             MemberAccessNode->AccessOperators.Append(LatterMemberAccessNode->AccessOperators);
//                             MemberAccessNode->AccessChain.Append(LatterMemberAccessNode->AccessChain);
//                         }
//                         else
//                         {
//                             MemberAccessNode->AccessOperators.Add(NextToken);
//                             MemberAccessNode->AccessChain.Add(NextSentenceNode);
//                         }

//                         It=std::next(It,2);
//                     }

//                     if(It== RawNodeList.end())
//                     {
//                         //it is the end
//                         return MemberAccessNode;
//                     }
                    
//                     auto NewList=std::list<RawASTNode>(It,RawNodeList.end());
//                     NewList.push_front(std::static_pointer_cast<CExpressionNode>(MemberAccessNode));
                    
//                     return BuildExpression(NewList);
//                 }

//                 case EScriptTokenType::PlusPlus:
//                 case EScriptTokenType::MinusMinus:
//                 {
//                     auto MonoOperatorNode = std::make_shared<CMonocularOperatorNode>(Context);
//                     MonoOperatorNode->Operator = Token;
//                     MonoOperatorNode->Operand=BuildExpression( std::list<RawASTNode>(RawNodeList.begin(),  Found));
//                     MonoOperatorNode->bRight=true;
//                     auto NewList=std::list<RawASTNode>(std::next(Found),RawNodeList.end());
//                     NewList.push_front(std::static_pointer_cast<CExpressionNode>(MonoOperatorNode));
//                     return BuildExpression(NewList);
//                 }

            

//             };


//         }

//     }


//     WH::Cout()<<"parse sentence failed!"<<WH::EndL();
//     WH::Cout()<<"RawNodeList:"<<WH::EndL();

//     uint64_t i=0;
//     for(auto& Node : RawNodeList)
//     {
//         //print node index
//         WH::Cout()<<"\n["<<i<<"] : "<<WH::EndL();

//         if(Node.IsA<std::shared_ptr<CScriptToken>>())
//         {
//             WH::Cout()<<Node.Get<std::shared_ptr<CScriptToken>>()->ToString()<<WH::EndL();
//         }
//         else
//         {
//             Node.Get<std::shared_ptr<CExpressionNode>>()->DebugPrint(0);
//         }

//         i++;
//     }
   
//     std::shared_ptr<CScriptToken> Token;

//     if(RawNodeList.front().IsA<std::shared_ptr<CScriptToken>>())
//     {
//         Token=RawNodeList.front().Get<std::shared_ptr<CScriptToken>>();
//     }
//     else
//     {
//         Token=RawNodeList.front().Get<std::shared_ptr<CExpressionNode>>()->GetFirstToken();
//     }

//     if(Token)
//     {
//         Context->RaiseError(10116,Token,U"Parse failed");
//         return nullptr;
//     }

//     assert(false&& "parse failed!");
//     return nullptr;
// }

// void CExpressionBuilder::PushOperator(const SOperatorStackItem &InOperator)
// {
// }

std::shared_ptr<CExpressionNode> CExpressionBuilder::IteralTokens(int64_t InPrority)
{
    std::shared_ptr<CExpressionNode> Left;

    //address tokens that can exist at the beginning of expression
    //most token can exist at the beginning of expression

    auto FirstToken=Context->GetCurrentToken();

    if(FirstToken->Type==EScriptTokenType::Identifier)
    {
        //this might be a 
        //1.function call
        //2.identifier
        //do not care about member access here, it will be handled when building expression with operator . ->

        //check is function call

        bool IsFunctionCall=false;
        if((Context->CurrentTokenIndex+1)<EndTokenIndex)
        {
            auto NextToken=Context->GetToken(Context->CurrentTokenIndex+1);
            if(NextToken->Type == EScriptTokenType::LeftParentheses)
            {
                //this is a function call
                IsFunctionCall=true;
            }
        }

        if(IsFunctionCall)
        {
            auto FunctionCallBuilder = std::make_shared<CFunctionCallBuilder>(Context);
            if(!FunctionCallBuilder->ReadCurentToken())
            {
                return nullptr;
            }

            Left=std::static_pointer_cast<CExpressionNode> (FunctionCallBuilder->Result);
        }
        else
        {
            //this is a identifier
            auto IdentifierNode = std::make_shared<CIdentifierNode>(Context);
            IdentifierNode->Identifier = FirstToken;

            Left=std::static_pointer_cast<CExpressionNode> (IdentifierNode);
           
            Context->CurrentTokenIndex++;
        }


    }
    else if(FirstToken->Type == EScriptTokenType::LiteralChar
        || FirstToken->Type == EScriptTokenType::LiteralString
        || FirstToken->Type == EScriptTokenType::LiteralNumber
        || FirstToken->Type == EScriptTokenType::LiteralBool
        || FirstToken->Type == EScriptTokenType::Null)
    {
        auto LiterialNode = std::make_shared<CLiteralNode>(Context);
        LiterialNode->Value = FirstToken;

        Left=std::static_pointer_cast<CExpressionNode>(LiterialNode);
        //ExpressionStack.push(std::static_pointer_cast<CExpressionNode>(LiterialNode));
        Context->CurrentTokenIndex++;
    }
    else if(FirstToken->Type == EScriptTokenType::Value)
    {
        auto ValueNode = std::make_shared<CValueNode>(Context);
        ValueNode->Value = FirstToken;
        Left=std::static_pointer_cast<CExpressionNode>(ValueNode);
        //ExpressionStack.push(std::static_pointer_cast<CExpressionNode>(ValueNode));
        Context->CurrentTokenIndex++;
    }
    else if(FirstToken->Type == EScriptTokenType::LeftParentheses)
    {
        //type cast or parentheses
        //check if it is a type cast
        //find paired right parentheses

        auto RightParenthesesToken=
            FindPairedParentheses(Context->CurrentTokenIndex+1,Context);
        
        if(!RightParenthesesToken.HasValue() || RightParenthesesToken.GetValue()>=EndTokenIndex )
        {
            Context->RaiseError(10117,FirstToken,U"Expecting paired ')'");
            return nullptr;
        }

        uint64_t RightParenthesesIndex=RightParenthesesToken.GetValue();
        
        //check if it is a type cast
        bool bIsTypeCast=false;
        auto TokenNextToRightParentheses=Context->GetToken(RightParenthesesIndex+1);
        if(TokenNextToRightParentheses->Type == EScriptTokenType::Identifier
            || TokenNextToRightParentheses->Type == EScriptTokenType::LeftParentheses
            || TokenNextToRightParentheses->Type == EScriptTokenType::LiteralChar
            || TokenNextToRightParentheses->Type == EScriptTokenType::LiteralString
            || TokenNextToRightParentheses->Type == EScriptTokenType::LiteralNumber
            || TokenNextToRightParentheses->Type == EScriptTokenType::LiteralBool
            || TokenNextToRightParentheses->Type == EScriptTokenType::Null
            || TokenNextToRightParentheses->Type == EScriptTokenType::Value
        )
        {
            //this is a type cast
            bIsTypeCast=true;
        }

        if(bIsTypeCast)
        {

            auto TypeCastNode = std::make_shared<CTypeCastNode>(Context);
            TypeCastNode->LeftParentheses=FirstToken;
            
            Context->CurrentTokenIndex++; //skip left parentheses
            auto  TypeBuilder=std::make_shared<CTypeBuilder>(Context);
            if(!TypeBuilder->ReadCurentToken())
            {
                return nullptr;
            }

            TypeCastNode->Type= TypeBuilder->Result;

            //skip right parentheses
            assert(Context->CurrentTokenIndex==RightParenthesesIndex);
            Context->CurrentTokenIndex=RightParenthesesIndex+1;

            TypeCastNode->Expression= IteralTokens(GetOperatorPriority(EOperator::TypeCast));

            Left=std::static_pointer_cast<CExpressionNode>(TypeCastNode);

        }
        else
        {
            //this is a parentheses
            auto ParenthesesNode = std::make_shared<CParenthesesNode>(Context);
            ParenthesesNode->LeftParentheses = FirstToken;

            Context->CurrentTokenIndex++; //skip left parentheses

            auto ExpressionBuilder=std::make_shared<CExpressionBuilder>(Context,RightParenthesesIndex);
            if(!ExpressionBuilder->ReadCurentToken())
            {
                return nullptr;
            }

            ParenthesesNode->Expression=ExpressionBuilder->Result;


            Left=std::static_pointer_cast<CExpressionNode>(ParenthesesNode);
            
            //skip right parentheses
            assert(Context->CurrentTokenIndex==RightParenthesesIndex);
            Context->CurrentTokenIndex=RightParenthesesIndex+1;
        }



    }    
    else if(FirstToken->Type==EScriptTokenType::Minus)
    {
        //this is a negative expression
        Context->CurrentTokenIndex++;

        auto NegativeExpression=std::make_shared<CNegativeNode>(Context);
        NegativeExpression->Minus=FirstToken;
        NegativeExpression->Value= IteralTokens(GetOperatorPriority(EOperator::Negtive));
        
        if(!NegativeExpression->Value)
        {
            Context->RaiseError(10118,FirstToken,U"Expecting operand after -");
            return nullptr;
        }

        Left=std::static_pointer_cast<CExpressionNode>(NegativeExpression);
    }
    else if(FirstToken->Type==EScriptTokenType::Plus)
    {
        //this is a positive expression,ignore +
        Context->CurrentTokenIndex++;

        std::shared_ptr<CExpressionNode> Operand= IteralTokens(GetOperatorPriority(EOperator::Positive));

        if(!Operand)
        {
            Context->RaiseError(10118,FirstToken,U"Expecting operand after +");
            return nullptr;
        }

        Left=Operand;

    }
    else if(FirstToken->Type==EScriptTokenType::PlusPlus
        ||FirstToken->Type==EScriptTokenType::MinusMinus
        ||FirstToken->Type==EScriptTokenType::NotOperator
        ||FirstToken->Type==EScriptTokenType::Tilde
        )
    {
        // this is a ++i or --i or !i or ~i
        Context->CurrentTokenIndex++;
     
        auto MonoOperatorNode = std::make_shared<CMonocularOperatorNode>(Context);
        MonoOperatorNode->Operator = FirstToken;
        int64_t Prority=-1;
        switch(FirstToken->Type)
        {
            case EScriptTokenType::PlusPlus:
                Prority=GetOperatorPriority(EOperator::LeftIncrement);
                break;
            case EScriptTokenType::MinusMinus:
                Prority=GetOperatorPriority(EOperator::LeftDecrement);
                break;
            case EScriptTokenType::NotOperator:
                Prority=GetOperatorPriority(EOperator::Not);
                break;
            case EScriptTokenType::Tilde:
                Prority=GetOperatorPriority(EOperator::BitNot);
                break;
            default:
                assert(false&&"unreachable");
                break;
        }

        MonoOperatorNode->Operand=IteralTokens(Prority);
        MonoOperatorNode->bRight=false;

        if(!MonoOperatorNode->Operand)
        {
            Context->RaiseError(10118,FirstToken,U"Expecting operand after ++/--");
            return nullptr;
        }

        Left=std::static_pointer_cast<CExpressionNode>(MonoOperatorNode);
        //ExpressionStack.push(std::static_pointer_cast<CExpressionNode>(MonoOperatorNode));
    }
    else
    {
        //raise error, expression cant start with this token
        Context->RaiseError(10119,FirstToken,U"Expression cant start with this token");
        return nullptr;
    }

    //address binary operator
    while (Context->CurrentTokenIndex<EndTokenIndex)
    {
        auto Token=Context->GetCurrentToken();

        int64_t Prority=-1;
        switch(Token->Type)
        {
            case EScriptTokenType::Plus:
                Prority=GetOperatorPriority(EOperator::Add);
                break;
            case EScriptTokenType::Minus:
                Prority=GetOperatorPriority(EOperator::Sub);
                break;
            case EScriptTokenType::Multiply:
                Prority=GetOperatorPriority(EOperator::Multiply);
                break;
            case EScriptTokenType::Divide:
                Prority=GetOperatorPriority(EOperator::Divide);
                break;
            case EScriptTokenType::Mod:
                Prority=GetOperatorPriority(EOperator::Mod);
                break;
            case EScriptTokenType::LeftShift:
                Prority=GetOperatorPriority(EOperator::LeftShift);
                break;
            case EScriptTokenType::RightShift:
                Prority=GetOperatorPriority(EOperator::RightShift);
                break;
            case EScriptTokenType::Less:
                Prority=GetOperatorPriority(EOperator::Less);
                break;
            case EScriptTokenType::LessEqual:
                Prority=GetOperatorPriority(EOperator::LessEqual);
                break;
            case EScriptTokenType::Greater:
                Prority=GetOperatorPriority(EOperator::Greater);
                break;
            case EScriptTokenType::GreaterEqual:
                Prority=GetOperatorPriority(EOperator::GreaterEqual);
                break;
            case EScriptTokenType::Equal:
                Prority=GetOperatorPriority(EOperator::Equal);
                break;
            case EScriptTokenType::NotEqual:
                Prority=GetOperatorPriority(EOperator::NotEqual);
                break;
            case EScriptTokenType::And:
                Prority=GetOperatorPriority(EOperator::BitAnd);
                break;
            case EScriptTokenType::Xor:
                Prority=GetOperatorPriority(EOperator::BitXor);
                break;
            case EScriptTokenType::Or:
                Prority=GetOperatorPriority(EOperator::BitOr);
                break;
            case EScriptTokenType::AndAnd:
                Prority=GetOperatorPriority(EOperator::And);
                break;
            case EScriptTokenType::OrOr:
                Prority=GetOperatorPriority(EOperator::Or);
                break;
            case EScriptTokenType::Dot:
                Prority=GetOperatorPriority(EOperator::Dot);
                break;
            case EScriptTokenType::Arrow:
                Prority=GetOperatorPriority(EOperator::Arrow);
                break;
            case EScriptTokenType::LeftBracket:
                Prority=GetOperatorPriority(EOperator::Bracket);
                break;

            case EScriptTokenType::Question:
                Prority=GetOperatorPriority(EOperator::Conditional);
                break;
            case EScriptTokenType::PlusPlus:
                Prority=GetOperatorPriority(EOperator::Increment);
                break;
            case EScriptTokenType::MinusMinus:
                Prority=GetOperatorPriority(EOperator::Decrement);
                break;

            default:
            {
                //require a operator here
                Context->RaiseError(10120,Token,U"Expecting a operator");
                return nullptr;
            }
            break;
        }

        if(Prority<=InPrority)
        {
            //this is not a operator of this level
            return Left;
        }

        if(Token->Type==EScriptTokenType::PlusPlus
            || Token->Type==EScriptTokenType::MinusMinus
        )
        {
            //this is a i++ or i--
            auto MonoOperatorNode = std::make_shared<CMonocularOperatorNode>(Context);
            MonoOperatorNode->Operator = Token;
            MonoOperatorNode->Operand=Left;
            MonoOperatorNode->bRight=true;

            //skip operator
            Context->CurrentTokenIndex++;

            Left=std::static_pointer_cast<CExpressionNode>(MonoOperatorNode);
            continue;
        }

        if(Token->Type == EScriptTokenType::Question)
        {
            //this is a conditional operator
            auto QuestionColonNode = std::make_shared<CQuestionColonOperatorNode>(Context);
            QuestionColonNode->Condition=Left;
           
            //find ':'
            int32_t ColonIndex=-1;
            {
                auto ColonToken= FindNextToken(EScriptTokenType::Colon,Context);
                if(!ColonToken.HasValue() || ColonToken.GetValue()>=EndTokenIndex )
                {
                    Context->RaiseError(10121,Token,U"Expecting paired ':' after '?'");
                    return nullptr;
                }
                ColonIndex=ColonToken.GetValue();
            }

            //skip '?'
            Context->CurrentTokenIndex++;

            auto TrueBranchBuilder= std::make_shared<CExpressionBuilder>(Context,ColonIndex);
            if(!TrueBranchBuilder->ReadCurentToken())
            {
                return nullptr;
            }
            QuestionColonNode->TrueBranch=TrueBranchBuilder->Result;

            //skip ':'
            Context->CurrentTokenIndex++;

            QuestionColonNode->FalseBranch=IteralTokens(Prority);

            Left=std::static_pointer_cast<CExpressionNode>(QuestionColonNode);

            continue;
        }

        if(Token->Type == EScriptTokenType::Dot || Token->Type == EScriptTokenType::Arrow)
        {
            //this is a member access operator

            //check if left operand is a member access node
            std::shared_ptr<CMemberAccessNode> MemberAccessNode;
            if(Left->Type==EASTNodeType::MemberAccess)
            {
                MemberAccessNode=std::static_pointer_cast<CMemberAccessNode>(Left);
            }
            else
            {
                MemberAccessNode = std::make_shared<CMemberAccessNode>(Context);
                MemberAccessNode->AccessChain.Add(Left);
            }

            MemberAccessNode->AccessOperators.Add(Token);

            //skip operator
            Context->CurrentTokenIndex++;

            auto RightOperand=IteralTokens(Prority);
            if(!RightOperand)
            {
                return nullptr;
            }

            if(RightOperand->Type==EASTNodeType::MemberAccess)
            {
                auto RightMemberAccessNode=std::static_pointer_cast<CMemberAccessNode>(RightOperand);
                MemberAccessNode->AccessChain.Append(RightMemberAccessNode->AccessChain);
                //MemberAccessNode->AccessOperators.Add(RightMemberAccessNode->AccessChain[0]->GetFirstToken());
                MemberAccessNode->AccessOperators.Append(RightMemberAccessNode->AccessOperators);
            }
            else
            {
                MemberAccessNode->AccessChain.Add(RightOperand);
            }

            Left=std::static_pointer_cast<CExpressionNode>(MemberAccessNode);
            continue;
        }

        if(Token->Type == EScriptTokenType::LeftBracket)
        {
            //this is a index access operator

            //check if left operand is a member access node
            std::shared_ptr<CMemberAccessNode> MemberAccessNode;
            if(Left->Type==EASTNodeType::MemberAccess)
            {
                MemberAccessNode=std::static_pointer_cast<CMemberAccessNode>(Left);
            }
            else
            {
                MemberAccessNode = std::make_shared<CMemberAccessNode>(Context);
                MemberAccessNode->AccessChain.Add(Left);
            }

            MemberAccessNode->AccessOperators.Add(Token);

            auto IndexerAccessBuilder=std::make_shared<CSentenceIndexerBuilder>(Context);
            if(!IndexerAccessBuilder->ReadCurentToken())
            {
                return nullptr;
            }

            MemberAccessNode->AccessChain.Add(IndexerAccessBuilder->Result);

            Left=std::static_pointer_cast<CExpressionNode>(MemberAccessNode);

            continue;
        }        

        //this must be a binary operator

        //skip  operator
        Context->CurrentTokenIndex++;

        auto BinocularOperatorNode = std::make_shared<CBinocularOperatorNode>(Context);
        BinocularOperatorNode->LeftOperand=Left;
        BinocularOperatorNode->Operator = Token;

        BinocularOperatorNode->RightOperand=IteralTokens(Prority);

        if(!BinocularOperatorNode->RightOperand)
        {
            Context->RaiseError(10121,Token,U"Expecting right operand after binary operator");
            return nullptr;
        }

        Left=std::static_pointer_cast<CExpressionNode>(BinocularOperatorNode);

    }

    assert(Context->CurrentTokenIndex==EndTokenIndex);
    return Left;
}
